package conditionsAPI;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Para usar la api hay que seguir los siguientes pasos:
 * 1_ Implementar clases que hereden de SimpleDomainCondition y representen las validaciones del dominio del problema
 * 2_ Armar arbol usando clases implementadas, AndCondition, NotCondition, ..
 * 3_ Definir el target en que se desea verificar ConditionsConfiguration::setTarget
 * 4_ Analizar coleccion de objetos de dominio con ConditionsConfiguration::processObjects
 * 5_ El resultado se obtiene la condicion del arbol que nos interesa o usando 
 * ConditionsConfiguration::getLastConditionFulfilled.
 */
public class ConditionsConfiguration {

	private static HashMap<String,Condition> conditionsConfigured = new HashMap<String,Condition>();
	private static ConditionListener listener = new ConditionsConfigurationListener();
	private static Condition target = null;
	private static String targetResult = "";
	
	protected static void addCondition(Condition condition) throws ConditionDuplicatedException
	{
		String conditionId = condition.getId();
		if (!conditionsConfigured.containsKey(conditionId)){
			conditionsConfigured.put(conditionId, condition);
		}
		else throw new ConditionDuplicatedException();
	}
	
	public static void processObjects(Collection<Object> domainObjects){
		Iterator<Object> domainObjectsIterator = domainObjects.iterator();
		while (domainObjectsIterator.hasNext()){
			Object domainObject = domainObjectsIterator.next();
			notifyConditions(domainObject);
		}
	}
	
	public static void processObject(Object domainObject){
		notifyConditions(domainObject);
	}
	
	public static void resetConditions(){
		Iterator<Condition> conditionsIterator = conditionsConfigured.values().iterator();
		while (conditionsIterator.hasNext()){
			Condition condition = conditionsIterator.next();
			condition.resetState();
		}
	}
	
	private static void notifyConditions(Object domainObject){
		Iterator<Condition> conditionsIterator = conditionsConfigured.values().iterator();
		while (conditionsIterator.hasNext()){
			Condition condition = conditionsIterator.next();
			condition.updateState(domainObject);
		}
	}
	
	public static boolean setTarget(DomainCondition domainCondition){
		Condition condition = domainCondition.getCondition();
		String conditionId = condition.getId();
		if (conditionsConfigured.containsKey(conditionId)){
			target = condition;
			target.addConditionListener(listener);
			return true;
		}
		return false;
	}
	
	public static String getLastConditionFulfilled(){
		return targetResult;
	}
	
	public static void reset(){
		conditionsConfigured.clear();
		target = null;
		targetResult = "";
	}
	
	static class ConditionsConfigurationListener implements ConditionListener{
		@Override
		public void onConditionStateUpdated(Condition condition) {
			if (condition.isTrue()){
				targetResult = condition.getId();
			}
			else{
				targetResult = "";
			}
		}
	}
}
